/*
 * tcpserver.h
 *
 *  Created on: 2011-8-24
 *      Author: chenl
 *     Purpose:
 *        Note:
 */

#ifndef TCPSERVER_H_
#define TCPSERVER_H_

#include "common_connect.h"
#include "common_libnamespace.h"
#include "common_err.h"

#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <string.h>


CHENLIB_NAMESPACE_BEGIN

class CTcpServer
{
public:
	CTcpServer();
	virtual ~CTcpServer();
public:
	int32_t Start()
	{
		if (m_bStarted)
		{
			return S_FALSE;
		}
		m_nListenFD = socket(AF_INET, SOCK_STREAM, 0);
		if (m_nListenFD <= 0)
		{
			return E_CREATESOCKERR;
		}
		m_serverAddr.sin_family = AF_INET;
		inet_pton(AF_INET, INADDR_ANY, &m_serverAddr.sin_addr);
		m_serverAddr.sin_port = htons(m_port);

		int32_t ret = S_OK;
		int on = 1;
		ret = setsockopt(m_nListenFD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
		if (0 > ret)
		{
			return ret;
		}
		ret = bind(m_nListenFD, (struct sockaddr*)&m_serverAddr, sizeof(m_serverAddr));
		if (0 > ret)
		{
			return ret;
		}
		ret = listen(m_nListenFD, SOMAXCONN);
		if (0 > ret)
		{
			return ret;
		}
		m_bStarted = true;
		return ret;
	}
	int32_t Stop()
	{
		close(m_nListenFD);
		m_bStarted = false;
		return S_OK;
	}
	int32_t Accept(int &fd)
	{
		fd = accept(m_nListenFD, NULL, NULL);
		if (-1 == fd)
		{
			return E_SOCKACCEPTERR;
		}
		return S_OK;
	}
	int GetFD() const
	{
		return m_nListenFD;
	}
	void SetPort(int port)
	{
		m_port = port;
	}
private:
	CTcpServer(const CTcpServer&);
	CTcpServer &operator==(const CTcpServer&);
private:
	bool m_bStarted;
	int m_nListenFD;
	int m_port;
	struct sockaddr_in m_serverAddr;
};

CHENLIB_NAMESPACE_END

#endif /* TCPSERVER_H_ */
